package com.unibeta.cloudtest.springboot.util;

import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.security.crypto.encrypt.AesBytesEncryptor;

import com.unibeta.cloudtest.config.CacheManager;
import com.unibeta.cloudtest.config.CacheManagerFactory;
import com.unibeta.cloudtest.springboot.config.AppContext;
import com.unibeta.cloudtest.springboot.config.CloudTestProperties;
import com.unibeta.cloudtest.tool.Tools;

public class StarterUtils {

	private static final String CLOUDTEST_SPRINGBOOT_STARTER = "cloudtest_springboot_starter";

	private StarterUtils() {
	}

	static CloudTestProperties cloudTestProperties;

	private static AesBytesEncryptor aesBytesEncryptor = new AesBytesEncryptor(getCloudTestProperties().getPassword(),
			getCloudTestProperties().getAesKey());

	private static CloudTestProperties getCloudTestProperties() {
		if (cloudTestProperties == null) {
			cloudTestProperties = AppContext.getApplicationContext().getBean(CloudTestProperties.class);
		}

		return cloudTestProperties;
	}

	public static String signToken(String password, int validDays) {
		AesBytesEncryptor aes = new AesBytesEncryptor(password, getCloudTestProperties().getAesKey());
		return Base64.getEncoder()
				.encodeToString(aes.encrypt(generateToken(validDays).values().toArray()[0].toString().getBytes()));
	}

	public static boolean authToken(String token) {

		if (StringUtils.isBlank(token)) {
			return false;
		} else {
			try {
				String decoded = null;

				CacheManager globalCacheInstance = CacheManagerFactory.getGlobalCacheInstance();
				if (globalCacheInstance.get(CLOUDTEST_SPRINGBOOT_STARTER, token) != null) {
					decoded = (String) globalCacheInstance.get(CLOUDTEST_SPRINGBOOT_STARTER, token);
				} else {
					decoded = new String(Base64.getDecoder()
							.decode(aesBytesEncryptor.decrypt(Base64.getDecoder().decode(token.getBytes()))))
							.replaceAll("\\D", "");
					globalCacheInstance.put(CLOUDTEST_SPRINGBOOT_STARTER, token, decoded);
				}

				if (Tools.isNumeric(decoded)) {
					Long data = Long.valueOf(decoded);
					return new Date(data).after(new Date());
				}
			} catch (Throwable e) {
				return false;
			}
		}

		return false;
	}

	private static Map<String, String> generateToken(int validDays) {

		String signed = DateUtils.addDays(new Date(), validDays).getTime() + "";
		List<Character> list = new ArrayList<>();
		Random r = new Random();
		int salt = r.nextInt(93);

		for (int i = 0; i < signed.length(); i++) {
			list.add(signed.charAt(i));

			int random = r.nextInt();
			salt = salt % 83;
			int mod = random % (salt + 10);
			int key = Math.abs(mod) + (int) ' ';// 33:' '

			if (key >= (int) '0' && key <= (int) '9') { // 48:'0',58:'9'
				key += 10;
			}

			list.add((char) key);
		}

		StringBuffer buffer = new StringBuffer();
		for (Object c : list) {
			buffer.append(c);
		}

		String encode = Base64.getEncoder().encodeToString(buffer.toString().getBytes());

		Map<String, String> map = new HashMap<>();
		map.put(buffer.toString(), encode);

		return map;
	}
}
